using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using Peak.Can.Basic;

namespace WinCANTool
{


    public partial class FlashWindow1319 : Form
    {
        private byte[] Fragment;
		//private byte[][] SegData;
		
		
		public bool debug_flash = false;
        public const int FULL_FILE_SIZE = 10000000;
        public const uint WAIT_TIME = 0xffffffff;
		public const int KWP_SEND_ALL = 0x780;
        public uint TxNodeId=0x783;
        public uint RxNodeId=0x793;
        //public int[] FileSize;
        public int BLOCK_SIZE;
        public int ReturnValue = 0;
		public int data_download = 0;

        uint ReadCount = 0;
        private TPCANMsg CanMessageOut = new TPCANMsg();
        private TPCANMsg CanMessageIn = new TPCANMsg();
        private Queue<TPCANMsg> MsgQueue = new Queue<TPCANMsg>(1);
        public string FileInName;
        public int NodeId;
        public int FlashKeyIn;
        public int CommandObjectIndex;
        public int FileObjectIndex;
        public int SDODataValue;
        public int FullBlockCount;
		public int init_value = 0xff;
		public			int tx_index;

        //public int[] flashAddr;

        public byte ClientCommandSpecifier;
        private NewMessage MessageToSend = new NewMessage();
        public bool FlashOpOn = false;
        public bool SegmentWrite = false;
        public bool SegmentTransferON = false;
        public bool ValueWrite = false;
        public bool FileOpen = false;
        public bool MessageOk = false;
        public bool CTFTest1 = false;
        public bool CTFTest2 = false;
        public bool SendValue = false;
        public bool LastValue = false;
        public bool SendMessageON = false;
        public bool SetLastValue = false;
        public bool UseSecondChannel = false;
        private EventArgs Args = new EventArgs();
        //public event EventHandler FlashDone;
        public event EventHandler TickDone;
        public delegate void MessageOpHandler(object CurrentForm, MessageOpArgs ReturnResult);
        public event MessageOpHandler MessageOpDone;
        public event MessageOpHandler FlashOpDone;
        public MessageOpArgs OpArgs = new MessageOpArgs();
		public  string path_cur = System.IO.Directory.GetCurrentDirectory();  
		public string hardware_id;
		public string part_number;
		public int software_ver;
		public string software_id;

		public uint secacc_crypto_12( uint seed )
		{
		   /* calculate key */
		   const uint a = 0x974c58ab;
		   const uint b = 0xfedcba98;
		   const uint c = 0x98765432;
		   uint x = seed + a;

		   if( (0xffffffff - a) < seed)
		   {
		      x ^= b;
		   }
		   else
		   {
		      x ^= c;
		   }

		   x = (x >> 11) | ((x & 0x7ff) << 21);

		   return x;
		}

		public uint secacc_crypto_34( uint seed )
		{
		   return seed + 0x1AF7;
		}

		

		public void start_diagnostic()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x10;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x81;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x50)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}

	    public void read_hw_id()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x1A;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x80;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x5A)
        	{
            	ReturnValue = 0;
                int id = Convert.ToInt32(CanMessageIn.DATA[2]);	
				hardware_id =  Convert.ToString(id); 
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}

        public void write_partnumber()
		{
            byte[] decBytes = System.Text.Encoding.UTF8.GetBytes("12853605200"); 

            CanMessageOut.DATA[0] = 0x10;	    //	security 3/4
            CanMessageOut.DATA[1] = 0x0D;	// 	
            CanMessageOut.DATA[2] = 0x3B;
            CanMessageOut.DATA[3] = 0x0;
            CanMessageOut.DATA[4] = decBytes[0];
            CanMessageOut.DATA[5] = decBytes[1];
            CanMessageOut.DATA[6] = decBytes[2];
            CanMessageOut.DATA[7] = decBytes[3];
            
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
			CanMessageIn.DATA[1] = 0x00;

            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }				
            } while (MessageOk == false);
            
	
            if (CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
        	}
           
			Thread.Sleep(10);
			

            CanMessageOut.DATA[0] = 0x21;	    //	start default session
            CanMessageOut.DATA[1] = decBytes[4];	// 	7 bytes of Data
            CanMessageOut.DATA[2] = decBytes[5];
            CanMessageOut.DATA[3] = decBytes[6];
            CanMessageOut.DATA[4] = decBytes[7];
            CanMessageOut.DATA[5] = decBytes[8];
            CanMessageOut.DATA[6] = decBytes[9];
            CanMessageOut.DATA[7] = decBytes[10];
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);

            if (CanMessageIn.DATA[1] == 0x7B)
            {
                ReturnValue = 0;
            }
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		}	
        public void read_partnumber()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x21;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x00;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = -99;
				return;
        	}
           
			Thread.Sleep(10);
			

            CanMessageOut.DATA[0] = 0x30;	    //	start default session
            CanMessageOut.DATA[1] = 00;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x0A;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);

            if (CanMessageIn.DATA[0] == 0x21)
            {
                ReturnValue = 0;
            }
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}	

        public void read_brandid()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x21;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x03;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x61 || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
				if(CanMessageIn.DATA[1] == 0x61)
				{
	                int part_num = Convert.ToInt32(CanMessageIn.DATA[2]);	
					part_number =  Convert.ToString(part_num); 
				}
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}	


        public void read_ID36()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x21;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x36;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x61 || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}	
        public void read_ID20()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x21;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x20;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x61 || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}	
		

        public void read_IDC0()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x21;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0xC0;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x61 || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}			

        public void read_ecu_variant()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x21;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x80;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x61 || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
				if(CanMessageIn.DATA[1] == 0x61)
				{
	                int part_num = Convert.ToInt32(CanMessageIn.DATA[2]);	
					part_number =  Convert.ToString(part_num); 
				}
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}			


		

        public void read_swid()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x1A;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x81;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[2] == 0x5A || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
				if(CanMessageIn.DATA[2] == 0x5A)
	                software_id = Convert.ToString(CanMessageIn.DATA[3]);
				else
					return;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			Thread.Sleep(10);
			

            CanMessageOut.DATA[0] = 0x30;	    //	start default session
            CanMessageOut.DATA[1] = 00;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x0A;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);

            if (CanMessageIn.DATA[0] == 0x21)
            {
                ReturnValue = 0;
                software_id += Convert.ToString(CanMessageIn.DATA[1]);
            }
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		}	


        public void read_swid2()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x1A;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x82;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[2] == 0x5A || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
				if(CanMessageIn.DATA[2] == 0x5A)
	                software_id = Convert.ToString(CanMessageIn.DATA[3]);
				else
					return;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			Thread.Sleep(10);
			

            CanMessageOut.DATA[0] = 0x30;	    //	start default session
            CanMessageOut.DATA[1] = 00;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x0A;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);

            if (CanMessageIn.DATA[0] == 0x21)
            {
                ReturnValue = 0;
                software_id += Convert.ToString(CanMessageIn.DATA[1]);
            }
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		}			

        public void read_swid3()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x1A;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x83;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[2] == 0x5A || CanMessageIn.DATA[1] == 0x7f)
        	{
	            ReturnValue = 0;
				if(CanMessageIn.DATA[2] == 0x5A)
	                software_id = Convert.ToString(CanMessageIn.DATA[3]);
				else
					return;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			Thread.Sleep(10);
			

            CanMessageOut.DATA[0] = 0x30;	    //	start default session
            CanMessageOut.DATA[1] = 00;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x0A;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);

            if (CanMessageIn.DATA[0] == 0x21)
            {
                ReturnValue = 0;
                software_id += Convert.ToString(CanMessageIn.DATA[1]);
            }
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		}


        public void read_software_version()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x1A;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x84;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x5A || CanMessageIn.DATA[1] == 0x7F)
        	{
	            ReturnValue = 0;
				if(CanMessageIn.DATA[1] == 0x5A)
				{
					software_ver = Convert.ToInt16(CanMessageIn.DATA[2]);
				}
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}		
		

        public void stop_diagnostic()
		{
            CanMessageOut.DATA[0] = 1;	    //	start default session
            CanMessageOut.DATA[1] = 0x20;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0xff;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x60)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}

        public void seacc_ff()
		{
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x27;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0xff;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x7f)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
		
		}		
		

		public void start_programming()
		{
			CanMessageOut.ID = KWP_SEND_ALL;
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x10;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x85;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x50)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			CanMessageOut.ID = TxNodeId;
		
		}

		public void write_param(byte id, byte[] value, byte length)
		{			
            CanMessageOut.DATA[0] = length;	    //	security 3/4
            CanMessageOut.DATA[1] = 0x3B;	// 	
            CanMessageOut.DATA[2] = id;

			for(int i = 3; i < 8; i++)
			{
	            CanMessageOut.DATA[i] = 0xff;
			}			

			for(int i = 0; i < length-2; i++)
			{
	            CanMessageOut.DATA[3+i] = value[i];
			}
            
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
			CanMessageIn.DATA[1] = 0x00;

            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }				
            } while ((CanMessageIn.DATA[1] != 0x7B) && (CanMessageIn.DATA[3] != 0x12));
            
            if (CanMessageIn.DATA[1] == 0x7B || CanMessageIn.DATA[1] == 0x7F)
        	{
	            ReturnValue = 0;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
			
		}
		
		

		public void secacc_process_34()
		{
			uint sec_seed;
			uint sec_key;
			byte[] temp_data;
            CanMessageOut.DATA[0] = 2;	    //	security 3/4
            CanMessageOut.DATA[1] = 0x27;	// 	
            CanMessageOut.DATA[2] = 0x03;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x67)
        	{
	            ReturnValue = 0;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
			
			sec_seed = CanMessageIn.DATA[3];
			sec_seed |= ((uint)CanMessageIn.DATA[4]) << 8;
			sec_seed |= ((uint)CanMessageIn.DATA[5]) << 16;
			sec_seed |= ((uint)CanMessageIn.DATA[6]) << 24;
			sec_key = secacc_crypto_34(sec_seed);

			temp_data = BitConverter.GetBytes(sec_key);
			Thread.Sleep(10);

            CanMessageOut.DATA[0] = 6;	    //	start default session
            CanMessageOut.DATA[1] = 0x27;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x04;
            CanMessageOut.DATA[3] = temp_data[0];
            CanMessageOut.DATA[4] = temp_data[1];
            CanMessageOut.DATA[5] = temp_data[2];
            CanMessageOut.DATA[6] = temp_data[3];
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x67)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
		}


		public void secacc_process_56()
		{
			uint sec_seed;
			uint sec_key;
			byte[] temp_data;
            CanMessageOut.DATA[0] = 2;	    //	security 5/6
            CanMessageOut.DATA[1] = 0x27;	// 	
            CanMessageOut.DATA[2] = 0x05;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x67)
        	{
	            ReturnValue = 0;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			Thread.Sleep(10);
			
			sec_seed = CanMessageIn.DATA[3];
			sec_seed |= ((uint)CanMessageIn.DATA[4]) << 8;
			sec_seed |= ((uint)CanMessageIn.DATA[5]) << 16;
			sec_seed |= ((uint)CanMessageIn.DATA[6]) << 24;
			sec_key = secacc_crypto_56(sec_seed);

			temp_data = BitConverter.GetBytes(sec_key);			

            CanMessageOut.DATA[0] = 6;	    //	start default session
            CanMessageOut.DATA[1] = 0x27;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x06;
            CanMessageOut.DATA[3] = temp_data[0];
            CanMessageOut.DATA[4] = temp_data[1];
            CanMessageOut.DATA[5] = temp_data[2];
            CanMessageOut.DATA[6] = temp_data[3];
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x67)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
		}
		

		public void enter_passive_mode()
		{
			CanMessageOut.ID = KWP_SEND_ALL;

            CanMessageOut.DATA[0] = 3;	    //	enter passive mode
            CanMessageOut.DATA[1] = 0x31;	// 	
            CanMessageOut.DATA[2] = 0x04;
            CanMessageOut.DATA[3] = 0;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x71)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
			CanMessageOut.ID = TxNodeId;
		}

		public void flash_data(int seg_no)
		{
            int BytesRead, BlockCtr = 0;
			byte[] block_full_byte;
			int block_cnt_full;
			int block_left_bytes;
			int blockIndex = 0;
			//int block_cnt;
			int remain_cnt;
			byte segIndex;
			int seg_cnt;
			byte[] temp_data;

			temp_data = new byte[8];
            block_full_byte = new byte[2];
			Thread.Sleep(10);
			request_download(seg_no);
			Thread.Sleep(10);
			delete_flash(seg_no);
			Thread.Sleep(10);
			data_download = 1;
			BlockCtr = FileSize[seg_no] / BLOCK_SIZE;
			if(FileSize[seg_no] % BLOCK_SIZE != 0)
			{
				BlockCtr++;
			}				
  
            FullBlockCount  = BlockCtr;

			block_cnt_full = (BLOCK_SIZE - 5)/7; // first block will be five

			block_left_bytes = (BLOCK_SIZE - 5)%7;

			tx_index = 0;

			init_value = 0;


			block_full_byte = BitConverter.GetBytes(BLOCK_SIZE + 1);

            blockIndex = 0;
            while (BlockCtr - 1 > 0)		// handle full(whole) blocks first            
            {
                CanMessageOut.DATA[0] = 0x10;
                CanMessageOut.DATA[0] += block_full_byte[1];	//	Sequence Counter
                CanMessageOut.DATA[1] = block_full_byte[0];	// 	7 bytes of Data
                CanMessageOut.DATA[2] = 0x36;
                CanMessageOut.DATA[3] = SegData[seg_no][tx_index++];
                CanMessageOut.DATA[4] = SegData[seg_no][tx_index++];
                CanMessageOut.DATA[5] = SegData[seg_no][tx_index++];
                CanMessageOut.DATA[6] = SegData[seg_no][tx_index++];
                CanMessageOut.DATA[7] = SegData[seg_no][tx_index++];

	            MessageToSend.ConvertNewMessage(CanMessageOut);
	            SendFlashMessage(MessageToSend);
				Thread.Sleep(1);


	            MessageOk = false;
				if(debug_flash)
				{
					ReadCount = 100;
				}
				else
				{
		            ReadCount = WAIT_TIME;
				}
			
	            do
	            {
	                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
	                if (ReadCount-- == 0)
	                {
					    if(debug_flash)
				    	{
				    		break;
				    	}
	                    OpArgs.ReturnOpValue = ReturnValue;
	                    SendMessageEndEvent(OpArgs);
	                }

	            } while (MessageOk == false);
	            
	            if (CanMessageIn.DATA[1] == 0x00 || debug_flash)
	                ReturnValue = 0;
	            else
	            {
	                ReturnValue = -99;
	                OpArgs.ReturnOpValue = ReturnValue;
	                SendMessageEndEvent(OpArgs);
	            }


				for(segIndex = 0; segIndex < block_cnt_full; segIndex++)
				{
                    CanMessageOut.DATA[0] = 0x20;
                    temp_data = BitConverter.GetBytes((segIndex + 1) % 16);	//	Sequence Counter
                    CanMessageOut.DATA[0] += temp_data[0]; 
					
                    CanMessageOut.DATA[1] = SegData[seg_no][tx_index++];	// 	7 bytes of Data
                    CanMessageOut.DATA[2] = SegData[seg_no][tx_index++];
                    CanMessageOut.DATA[3] = SegData[seg_no][tx_index++];
                    CanMessageOut.DATA[4] = SegData[seg_no][tx_index++];
                    CanMessageOut.DATA[5] = SegData[seg_no][tx_index++];
                    CanMessageOut.DATA[6] = SegData[seg_no][tx_index++];
                    CanMessageOut.DATA[7] = SegData[seg_no][tx_index++];
                    MessageToSend.ConvertNewMessage(CanMessageOut);
                    SendFlashMessage(MessageToSend);
					Thread.Sleep(1);

				}

				if(block_left_bytes > 0)
				{
					remain_cnt = block_left_bytes;

	                temp_data = BitConverter.GetBytes((block_cnt_full + 1) % 16);	//	Sequence Counter
	                CanMessageOut.DATA[0] = 0x20;

	                CanMessageOut.DATA[0] += temp_data[0];	//	Sequence Counter


					for(int k = 1; k < remain_cnt + 1; k++)  // 256 - 5 - 35*7=
					{
	                    CanMessageOut.DATA[k] = SegData[seg_no][tx_index++];	// 	7 bytes of Data
					}
	                MessageToSend.ConvertNewMessage(CanMessageOut);
	                SendFlashMessage(MessageToSend);
					Thread.Sleep(1);


	                MessageOk = false;
					if(debug_flash)
					{
						ReadCount = 100;
					}
					else
					{
			            ReadCount = WAIT_TIME;
					}				
	                do
	                {
	                    MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
	                    if (ReadCount-- == 0)
	                    {
						    if(debug_flash)
					    	{
					    		break;
					    	}
	                        OpArgs.ReturnOpValue = ReturnValue;
	                        SendMessageEndEvent(OpArgs);
	                    }

	                } while (MessageOk == false);
	                
	                if (CanMessageIn.DATA[1] == 0x76 || debug_flash)
	                    ReturnValue = 0;
	                else
	                {
	                    ReturnValue = -99;
	                    OpArgs.ReturnOpValue = ReturnValue;
	                    SendMessageEndEvent(OpArgs);
	                }
				}

                SendTickEvent(Args);
                BlockCtr--;								// remaining number of blocks
                blockIndex++;
				Thread.Sleep(1);
            }			// all full blocks sent
            BytesRead = FileSize[seg_no] - blockIndex * BLOCK_SIZE;
			if(BytesRead != 0)
			{
				temp_data = BitConverter.GetBytes(BytesRead + 1);

				CanMessageOut.DATA[0] = 0x10;	//	Sequence Counter
				CanMessageOut.DATA[0] += temp_data[1];	//	Sequence Counter
				CanMessageOut.DATA[1] = temp_data[0];	// 	7 bytes of Data
				CanMessageOut.DATA[2] = 0x36;


				CanMessageOut.DATA[3] = SegData[seg_no][tx_index++];
				CanMessageOut.DATA[4] = SegData[seg_no][tx_index++];
				CanMessageOut.DATA[5] = SegData[seg_no][tx_index++];
				CanMessageOut.DATA[6] = SegData[seg_no][tx_index++];
				CanMessageOut.DATA[7] = SegData[seg_no][tx_index++];

				MessageToSend.ConvertNewMessage(CanMessageOut);
				SendFlashMessage(MessageToSend);
				Thread.Sleep(5);
				

				MessageOk = false;
				if(debug_flash)
				{
					ReadCount = 100;
				}
				else
				{
		            ReadCount = WAIT_TIME;
				}
				do
				{
					MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
					if (ReadCount-- == 0)
					{
					    if(debug_flash)
				    	{
				    		break;
				    	}
					    OpArgs.ReturnOpValue = ReturnValue;
					    SendMessageEndEvent(OpArgs);
					}

				} while (MessageOk == false);

				if (CanMessageIn.DATA[1] == 0x00 || debug_flash)
				{
					ReturnValue = 0;
				}
				else
				{
					ReturnValue = -99;
					OpArgs.ReturnOpValue = ReturnValue;
					SendMessageEndEvent(OpArgs);
				}


				seg_cnt = (BytesRead - 5) / 7;

				for (int j = 0; j < seg_cnt; j++)					// send remaining full sequence fragments
				{
					CanMessageOut.DATA[0] = 0x20;	//	Sequence Counter

					temp_data = BitConverter.GetBytes((j + 1) % 16);

					CanMessageOut.DATA[0] += temp_data[0];	//	Sequence Counter
					for ( int k = 1; k < 8; k++)
					{
						CanMessageOut.DATA[k] = SegData[seg_no][tx_index++];	// 	7 bytes of Data	(some of these might be DNC as this is the last block?
					}

					MessageToSend.ConvertNewMessage(CanMessageOut);
					SendFlashMessage(MessageToSend);
					Thread.Sleep(1);
				}


				BytesRead = (BytesRead - 5) % 7;


				if(BytesRead != 0)
				{
					CanMessageOut.DATA[0] = 0x20;	//	Sequence Counter
					temp_data = BitConverter.GetBytes((seg_cnt + 1) % 16);
					CanMessageOut.DATA[0] += temp_data[0];	//	Sequence Counter
					for (int  k = 1; k < BytesRead + 1; k++)
					{
						CanMessageOut.DATA[k] = SegData[seg_no][tx_index++];	// 	7 bytes of Data	(some of these might be DNC as this is the last block?
					}

					MessageToSend.ConvertNewMessage(CanMessageOut);
					SendFlashMessage(MessageToSend);
					Thread.Sleep(1);

					MessageOk = false;
					if(debug_flash)
					{
						ReadCount = 100;
					}
					else
					{
			            ReadCount = WAIT_TIME;
					}		
					do
					{
						//Thread.Sleep(1);
						MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
						if (ReadCount-- == 0)
						{
						    //SendFlashEndEvent(Args);
						    if(debug_flash)
					    	{
					    		break;
					    	}
						    OpArgs.ReturnOpValue = ReturnValue;
						    SendMessageEndEvent(OpArgs);
						}

					} while (MessageOk == false);

					if (CanMessageIn.DATA[1] == 0x76 || debug_flash)
					{
						ReturnValue = 0;
					}
					else
					{
						ReturnValue = -99;
						OpArgs.ReturnOpValue = ReturnValue;
						SendMessageEndEvent(OpArgs);
					}
					
				}
				SendTickEvent(Args);
				
			}
			data_download = 0;
            Thread.Sleep(10);
			
            request_transfer_exit(seg_no);
            Thread.Sleep(10);
			
            calculate_checksum(seg_no);
            Thread.Sleep(10);
		
		}

		public void start_flasher()
		{
			CanMessageOut.ID = KWP_SEND_ALL;

            CanMessageOut.DATA[0] = 3;	    //	start flasher
            CanMessageOut.DATA[1] = 0x31;	// 	
            CanMessageOut.DATA[2] = 0x01;
            CanMessageOut.DATA[3] = 0x00;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x71)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
			CanMessageOut.ID = TxNodeId;
		}

		public void secacc_process_12()
		{
			uint sec_seed;
			uint sec_key;
			byte[] temp_data;
            CanMessageOut.DATA[0] = 2;	    //	requeset seed1/2
            CanMessageOut.DATA[1] = 0x27;	// 	
            CanMessageOut.DATA[2] = 0x01;
            CanMessageOut.DATA[3] = 0x00;
            CanMessageOut.DATA[4] = 0x00;
            CanMessageOut.DATA[5] = 0x00;
            CanMessageOut.DATA[6] = 0x00;
            CanMessageOut.DATA[7] = 0x00;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x67)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
			Thread.Sleep(10);

			sec_seed = CanMessageIn.DATA[3];
			sec_seed |= ((uint)CanMessageIn.DATA[4]) << 8;
			sec_seed |= ((uint)CanMessageIn.DATA[5]) << 16;
			sec_seed |= ((uint)CanMessageIn.DATA[6]) << 24;

			sec_key = secacc_crypto_12(sec_seed);


			temp_data = BitConverter.GetBytes(sec_key);			

            CanMessageOut.DATA[0] = 6;	    //	start default session
            CanMessageOut.DATA[1] = 0x27;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x02;
            CanMessageOut.DATA[3] = temp_data[0];
            CanMessageOut.DATA[4] = temp_data[1];
            CanMessageOut.DATA[5] = temp_data[2];
            CanMessageOut.DATA[6] = temp_data[3];
            CanMessageOut.DATA[7] = 0x00;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x67)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }		
		
		}

		public void request_download(int seg_no)
		{
			byte[] temp_data;
			temp_data = BitConverter.GetBytes(flashAddr[seg_no]);

            CanMessageOut.DATA[0] = 0x10;	    //	request download
            CanMessageOut.DATA[1] = 0x0A;	    // 	start address
            CanMessageOut.DATA[2] = 0x34;
            CanMessageOut.DATA[3] = temp_data[0];
            CanMessageOut.DATA[4] = temp_data[1];
            CanMessageOut.DATA[5] = temp_data[2];
            CanMessageOut.DATA[6] = temp_data[3];				
            CanMessageOut.DATA[7] = 0x00; // invalid data
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x00)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
			Thread.Sleep(10);

			temp_data = BitConverter.GetBytes(FileSize[seg_no]);

            CanMessageOut.DATA[0] = 0x21;	    //	request download
            CanMessageOut.DATA[1] = temp_data[0];	    // 	length
            CanMessageOut.DATA[2] = temp_data[1];
            CanMessageOut.DATA[3] = temp_data[2];
            CanMessageOut.DATA[4] = temp_data[3];
            CanMessageOut.DATA[5] = 0x00;
            CanMessageOut.DATA[6] = 0x00;
            CanMessageOut.DATA[7] = 0x00;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x74)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
            BLOCK_SIZE = (int)CanMessageIn.DATA[2];
            BLOCK_SIZE |= ((int)CanMessageIn.DATA[3]) << 8;
		}

		public void delete_flash(int seg_no)
		{
			byte[] temp_data;
			temp_data = BitConverter.GetBytes(flashAddr[seg_no]);

            CanMessageOut.DATA[0] = 0x10;	    //	delete flash
            CanMessageOut.DATA[1] = 0x0a;	// 	
            CanMessageOut.DATA[2] = 0x31;
            CanMessageOut.DATA[3] = 0x02;
            CanMessageOut.DATA[4] = temp_data[0];
            CanMessageOut.DATA[5] = temp_data[1];
            CanMessageOut.DATA[6] = temp_data[2];
            CanMessageOut.DATA[7] = temp_data[3];
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;

		    do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x00)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			Thread.Sleep(10);
			
			
			temp_data = BitConverter.GetBytes(FileSize[seg_no]);

            CanMessageOut.DATA[0] = 0x21;	            //	deleted flash
            CanMessageOut.DATA[1] = temp_data[0];	    // 	length
            CanMessageOut.DATA[2] = temp_data[1];
            CanMessageOut.DATA[3] = temp_data[2];
            CanMessageOut.DATA[4] = temp_data[3];
            CanMessageOut.DATA[5] = 0x00;
            CanMessageOut.DATA[6] = 0x00;
            CanMessageOut.DATA[7] = 0x00;	   
			MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);


            MessageOk = false;
            ReadCount = WAIT_TIME;
			CanMessageIn.DATA[1] = 0x00;

            do
            {
				MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
				
                if(ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }
            } while (CanMessageIn.DATA[1] != 0x71);
            
            if (CanMessageIn.DATA[1] == 0x71)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                //SendFlashEndEvent(Args);
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }		
		}

		public void calculate_checksum(int seg_no)
		{
			byte[] temp_data;

			temp_data = BitConverter.GetBytes(flashAddr[seg_no]);			
			CanMessageOut.DATA[0] = 0x10;	//	calculate checksum
            CanMessageOut.DATA[1] = 0x0C;	// 
            CanMessageOut.DATA[2] = 0x31;
            CanMessageOut.DATA[3] = 0x03;
            CanMessageOut.DATA[4] = temp_data[0];
            CanMessageOut.DATA[5] = temp_data[1];
            CanMessageOut.DATA[6] = temp_data[2];
            CanMessageOut.DATA[7] = temp_data[3];

            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x00)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			Thread.Sleep(10);


			temp_data = BitConverter.GetBytes(FileSize[seg_no] - 1 + flashAddr[seg_no]);				

			CanMessageOut.DATA[0] = 0x21;	//	Sequence Counter
            CanMessageOut.DATA[1] = temp_data[0];	// 	7 bytes of Data
            CanMessageOut.DATA[2] = temp_data[1];

            
            CanMessageOut.DATA[3] = temp_data[2];
            CanMessageOut.DATA[4] = temp_data[3];

			temp_data = BitConverter.GetBytes(flash_checksum[seg_no]);				
			
            CanMessageOut.DATA[5] = temp_data[0];
            CanMessageOut.DATA[6] = temp_data[1];
            CanMessageOut.DATA[7] = 0x00;

            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x71)
        	{
	            ReturnValue = 0;
        	}
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }		
		}

		public void request_transfer_exit(int seg_no)
		{
			byte[] temp_data;

			temp_data = BitConverter.GetBytes(flashAddr[seg_no]);			


			
			CanMessageOut.DATA[0] = 0x10;	//	Request flash exit
            CanMessageOut.DATA[1] = 0x0A;	// 
            CanMessageOut.DATA[2] = 0x37;

            
            CanMessageOut.DATA[3] = temp_data[0];
            CanMessageOut.DATA[4] = temp_data[1];
            CanMessageOut.DATA[5] = temp_data[2];
            CanMessageOut.DATA[6] = temp_data[3];
            CanMessageOut.DATA[7] = 0x00;

            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x00)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
			Thread.Sleep(10);
			

			temp_data = BitConverter.GetBytes(FileSize[seg_no]);				

			CanMessageOut.DATA[0] = 0x21;	//	Sequence Counter
            CanMessageOut.DATA[1] = temp_data[0];	// 	7 bytes of Data
            CanMessageOut.DATA[2] = temp_data[1];

            
            CanMessageOut.DATA[3] = temp_data[2];
            CanMessageOut.DATA[4] = temp_data[3];
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;

            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);


            MessageOk = false;
            ReadCount = WAIT_TIME;
		
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x77)
                ReturnValue = 0;
            else
            {
                ReturnValue = -99;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }	
		
		}
		public void ecu_reset()
		{
            CanMessageOut.ID = KWP_SEND_ALL;
            CanMessageOut.DATA[0] = 2;	    //	start default session
            CanMessageOut.DATA[1] = 0x11;	// 	7 bytes of Data
            CanMessageOut.DATA[2] = 0x01;
            CanMessageOut.DATA[3] = 0xff;
            CanMessageOut.DATA[4] = 0xff;
            CanMessageOut.DATA[5] = 0xff;
            CanMessageOut.DATA[6] = 0xff;
            CanMessageOut.DATA[7] = 0xff;
            MessageToSend.ConvertNewMessage(CanMessageOut);
            SendFlashMessage(MessageToSend);

            MessageOk = false;
            ReadCount = WAIT_TIME;
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, RxNodeId);
                if (ReadCount-- == 0)
                {
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }

            } while (MessageOk == false);
            
            if (CanMessageIn.DATA[1] == 0x51)
                ReturnValue = 0;
            else
            {
                ReturnValue = 0;
                OpArgs.ReturnOpValue = ReturnValue;
                SendMessageEndEvent(OpArgs);
            }
            CanMessageOut.ID = TxNodeId;
		}

		public uint secacc_crypto_56( uint seed )
		{
		   uint rv;
		   Byte[] data;
           Byte[] data1;

		   data = new byte[4];
           data1 = new byte[4];

           data1 = BitConverter.GetBytes(seed);

            

		   data[3] = data1[0];

           data[2] = data1[1];

           data[1] = data1[2];

           data[0] = data1[3];

		   data[0] += 0x97;
		   data[1] += 0x28;
		   data[2] += 0xAA;
		   data[3] += 0x55;

		   rv = data[3];
		   rv <<= 8;
		   rv |= data[2];
		   rv <<= 8;
		   rv |= data[1];
		   rv <<= 8;
		   rv |= data[0];

		   return rv;
		}		


        public class MessageOpArgs : EventArgs
        {
            public int ReturnOpValue;

        }
        
        //public int GetBlockCount(string FileInName, int NodeId)
        public void GetBlockCount()
        {
			byte[] write_value;
			write_value = new byte[4];
                      
            FlashOpOn = true;

            SDOVarInit();

	        InitSegData();

            /**********  Transfer Control to Application ******************/
            CanMessageOut.LEN = 8;
            CanMessageOut.ID = TxNodeId;
            CanMessageOut.MSGTYPE = 0;

			start_diagnostic();
			Thread.Sleep(20);
			secacc_process_34();
			Thread.Sleep(20);
			enter_passive_mode();
			Thread.Sleep(20);
            start_flasher();
			Thread.Sleep(2000); // wait reset
			secacc_process_12();
			Thread.Sleep(20);
            start_programming();
			Thread.Sleep(20);
			delete_flash(0); //deleted last one

            for(int i = 0; i < 1; i++)
        	{
				flash_data(i);
        	}
			Thread.Sleep(20);
			stop_diagnostic();
			Thread.Sleep(20);
			ecu_reset();
            ReturnValue = 0;
            Thread.Sleep(4000);
			read_software_version();
            Thread.Sleep(20);
            read_swid();
			Thread.Sleep(20);
            read_brandid();
			Thread.Sleep(20);
			read_partnumber();
			Thread.Sleep(20);
            secacc_process_34();
			Thread.Sleep(20);
			enter_passive_mode();
			Thread.Sleep(20);
            secacc_process_56();

			write_value[0] = 0x00;
			write_value[1] = 0x01;

			write_param(3, write_value, 4);

			
			seacc_ff();
			Thread.Sleep(20);
			secacc_process_34();
			Thread.Sleep(20);
			start_flasher();
			Thread.Sleep(4000);
			secacc_process_12();
			start_programming();
			Thread.Sleep(20);
			ecu_reset();
			Thread.Sleep(4000);

			read_brandid();
			
			read_partnumber();
			Thread.Sleep(20);
			secacc_process_34();
			Thread.Sleep(20);
			enter_passive_mode();
			Thread.Sleep(20);
			write_partnumber();	
			Thread.Sleep(20);
			start_flasher();
			Thread.Sleep(4000);
			secacc_process_12();
			Thread.Sleep(20);
			start_programming();
			Thread.Sleep(20);
			ecu_reset();
			Thread.Sleep(4000);

            FileOpen = false;
            FlashOpOn = false;           
			OpArgs.ReturnOpValue = ReturnValue;
            SendMessageEndEvent(OpArgs); 

        }



        private int EndBlockDownload(int NodeId)
        {

            //626  110nnn01 00 00 00 00 00 00 00	//SDO MOSI, Node ID=0x26, Block Upload Transfer disconnect from client, Number of bytes not valid in previous segment=nnn(usually just = 0)
            for (int i = 0; i < 7; i++)
                Fragment[i] = 0;					// flush transmit buffer

            CanMessageOut.DATA[0] = 0xC1;	//	End Block Download
            CanMessageOut.DATA[1] = 0x00;	// 	7 bytes of Data	(all = 0)
            CanMessageOut.DATA[2] = 0x00;
            CanMessageOut.DATA[3] = 0x00;
            CanMessageOut.DATA[4] = 0x00;
            CanMessageOut.DATA[5] = 0x00;
            CanMessageOut.DATA[6] = 0x00;
            CanMessageOut.DATA[7] = 0x00;

            MessageToSend.ConvertNewMessage(CanMessageOut);
            //SendCanMessage(ref MessageToSend);
            SendFlashMessage(MessageToSend);

            //Thread.Sleep(1);

            //526  A1 00 00 00 00 00 00 00		//SDO MISO, Node ID=0x26, Block Upload Transfer disconnect from server

            MessageOk = false;
            ReadCount = WAIT_TIME;
            do
            {
                MessageOk = ReadCANMessage(ref CanMessageIn, 0x580);
                if (ReadCount-- == 0)
                    return -99;

            } while (MessageOk == false);

            if (CanMessageIn.DATA[0] == 0xA1)
                return 0;
            else
            {
                return -99;
            }        
        }



        public void CANValueTransfer()
        {
            if (ValueWrite)
                OpArgs.ReturnOpValue = SendSDOWrite();
            else
                OpArgs.ReturnOpValue = SendSDORead();
            FlashOpOn = false;
            //SendFlashEndEvent(Args);
            SendMessageEndEvent(OpArgs);

        }



        public void DeviseProfileThread()
        {

            
            while (!LastValue)
            {
                if (SendValue)
                {
                    if (SendMessageON)
                    {
                        if (SegmentTransferON)
                        {
                            if (SegmentWrite)
                                OpArgs.ReturnOpValue = (int) Segment_Transfer_Write(CommandObjectIndex, StringIn, NodeId);
                            else
                                OpArgs.ReturnOpValue = (int) Segment_Transfer_Read(CommandObjectIndex, StringData, NodeId);
                        }
                        else
                        {

                            if (ValueWrite)
                                OpArgs.ReturnOpValue = SendSDOWrite();
                            else
                                OpArgs.ReturnOpValue = SendSDORead();
                        }
                    }
                    
                    //if ((SetLastValue) || (ReturnValue != 0))
                    if (SetLastValue)
                        LastValue = true;
                    SendValue = false;
                    //SendFlashEndEvent(Args);
                    SendMessageEndEvent(OpArgs);
                    
                }
            }

        }




        public int SendSDORead()
        {
            int DataIn;
            
            FlashOpOn = true;
            SDOVarInit();
            SDODataValue = 0;
            ReturnValue = 0;

            CanMessageOut.LEN = 8;
            CanMessageOut.ID = 0x600 + (uint)NodeId;
            CanMessageOut.MSGTYPE = 0;



            if (CommandObjectIndex != 0)
            {

                CanMessageOut.DATA[0] = ClientCommandSpecifier;	                            //	CS_Byte
                CanMessageOut.DATA[1] = (byte)((CommandObjectIndex & 0x0000FF00) >> 8);	    // LSByte of Index
                CanMessageOut.DATA[2] = (byte)((CommandObjectIndex & 0x00FF0000) >> 16);	// MSByte of Index
                CanMessageOut.DATA[3] = (byte)(CommandObjectIndex & 0x000000FF);	        // SubIndex
                CanMessageOut.DATA[4] = (byte)((SDODataValue & 0x000000FF));	            // 	LSByte of LSWord
                CanMessageOut.DATA[5] = (byte)((SDODataValue & 0x0000FF00) >> 8);	        // 	MSByte of LSWord
                CanMessageOut.DATA[6] = (byte)((SDODataValue & 0x00FF0000) >> 16);	        // 	LSByte of MSWord
                CanMessageOut.DATA[7] = (byte)((SDODataValue & 0xFF000000) >> 24);	        // 	MSByte of MSWord


                MessageToSend.ConvertNewMessage(CanMessageOut);
                SendFlashMessage(MessageToSend);

                //Receive 5XX  60 AA AA BB CC CC CC CC	SDO MISO, Node ID=0xXX
                MessageOk = false;
                ReadCount = WAIT_TIME;

                do
                {
                    MessageOk = ReadCANMessage(ref CanMessageIn, 0x580);
                    if (ReadCount-- == 0)
                    {
                        //SendFlashEndEvent(Args);
                        ReturnValue = -99;
                        OpArgs.ReturnOpValue = ReturnValue;
                        SendMessageEndEvent(OpArgs);
                    }

                } while (MessageOk == false);

                //if (CanMessageIn.Data[0] == 0x60)
                //    ReturnValue = 1;
                //else
                //{
                //    ReturnValue = -99;
                //    SendFlashEndEvent(Args);
                //}

                if (CanMessageIn.DATA[0] == 0x80)
                {
                    ReturnValue = -99;
                    //SendFlashEndEvent(Args);
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);
                }
                DataIn = CanMessageIn.DATA[4] + (CanMessageIn.DATA[5] << 8) + (CanMessageIn.DATA[6] << 16) + (CanMessageIn.DATA[7] << 24);
                StringData1 = DataIn.ToString("X");

            }
            else
                ReturnValue = -99;

            return ReturnValue;
        }



        public int SendSDOWrite()
        {
            int DataIn;

            ReturnValue = 0;
            FlashOpOn = true;
            SDOVarInit();


            CanMessageOut.LEN = 8;
            CanMessageOut.ID = 0x600 + (uint)NodeId;
            CanMessageOut.MSGTYPE = 0;



            if (CommandObjectIndex != 0)
            {

                CanMessageOut.DATA[0] = ClientCommandSpecifier;	                            //	CS_Byte
                CanMessageOut.DATA[1] = (byte)((CommandObjectIndex & 0x0000FF00) >> 8);	    // LSByte of Index
                CanMessageOut.DATA[2] = (byte)((CommandObjectIndex & 0x00FF0000) >> 16);	// MSByte of Index
                CanMessageOut.DATA[3] = (byte)(CommandObjectIndex & 0x000000FF);	        // SubIndex
                CanMessageOut.DATA[4] = (byte)((SDODataValue & 0x000000FF));	            // 	LSByte of LSWord
                CanMessageOut.DATA[5] = (byte)((SDODataValue & 0x0000FF00) >> 8);	        // 	MSByte of LSWord
                CanMessageOut.DATA[6] = (byte)((SDODataValue & 0x00FF0000) >> 16);	        // 	LSByte of MSWord
                CanMessageOut.DATA[7] = (byte)((SDODataValue & 0xFF000000) >> 24);	        // 	MSByte of MSWord


                MessageToSend.ConvertNewMessage(CanMessageOut);
                SendFlashMessage(MessageToSend);

                //Receive 5XX  60 AA AA BB CC CC CC CC	SDO MISO, Node ID=0xXX
                MessageOk = false;
                ReadCount = WAIT_TIME;

                do
                {
                    MessageOk = ReadCANMessage(ref CanMessageIn, 0x580);
                    if (ReadCount-- == 0)
                    {
                        //SendFlashEndEvent(Args);
                        ReturnValue = -99;
                        OpArgs.ReturnOpValue = ReturnValue;
                        SendMessageEndEvent(OpArgs);
                    }

                } while (MessageOk == false);


                if (CanMessageIn.DATA[0] == 0x80)
                {
                    ReturnValue = -99;
                    OpArgs.ReturnOpValue = ReturnValue;
                    SendMessageEndEvent(OpArgs);

                }

                DataIn = CanMessageIn.DATA[4] + (CanMessageIn.DATA[5] << 8) + (CanMessageIn.DATA[6] << 16) + (CanMessageIn.DATA[7] << 24);
                StringData1 = DataIn.ToString("X");

            }
            else
                ReturnValue = -1;

            return ReturnValue;

        }

        public void ClearEvents()
        {
            if (FlashOpDone != null)
            {
                foreach (MessageOpHandler eventDelegate in FlashOpDone.GetInvocationList())
                    FlashOpDone -= eventDelegate;
            }
        }
        
        
        protected virtual void SendMessageEndEvent(MessageOpArgs e)
        {

            if (FileOpen)
            {
                FileOpen = false;
            }
            if (MessageOpDone != null)
                MessageOpDone(this, e);
            if (FlashOpDone != null)
                FlashOpDone(this, e);
        }
        
        protected virtual void SendTickEvent(EventArgs e)
        {

            if (TickDone != null)
                TickDone(this, e);
        }

        private void AddRXMessage(TPCANMsg MessageIn)
        {
            MsgQueue.Enqueue(MessageIn);
			if((this.CANMsgRxEvent != null) && (data_download == 0))
			{
			    //CANMsgRxEvent(ref MessageIn, true);	
			}
			
        }

        
        
        private bool ReadCANMessage(ref TPCANMsg MessageIn, uint MessageType)
        {
            bool MessageFound = false;

            if (MsgQueue.Count > 0)
            {
                MessageIn = MsgQueue.Dequeue();
                if (MessageIn.ID == MessageType)
                {
                    MessageFound = true;
					if((this.CANMsgRxEvent != null) && (data_download < 2))
					{
					    CANMsgRxEvent(ref MessageIn, true);	
					}					
                }
            }
            return MessageFound;
        }

        private void SDOVarInit()
        {
            MsgQueue.Clear();
            StringData1 = "";
        }


        private void SDOVarClear()
        {
            MsgQueue.Clear();
        
        }
    }
}
